//
// Created by xsh on 2025/5/30.
//
#include "jni.h"
#include "dlfcn.h"
#include <android/log.h>
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "JNI", __VA_ARGS__)
#define LOGD(tag,...) __android_log_print(ANDROID_LOG_DEBUG, tag, __VA_ARGS__)
static void* libstringfromso;
JNIEXPORT jstring JNICALL
Java_com_xsh_daw_MainActivity_getStringFromFunc(JNIEnv *env, jobject thiz, jstring libpath)
{
    const char *libPathC = (*env)->GetStringUTFChars(env, libpath, NULL);
    if (!libPathC) {
        LOGE("GetStringUTFChars failed");
        return (*env)->NewStringUTF(env, "GetStringUTFChars failed");
    }

    void *handle = dlopen(libPathC, RTLD_LAZY);
    if (!handle) {
        LOGE("dlopen failed: %s", dlerror());
        (*env)->ReleaseStringUTFChars(env, libpath, libPathC);
        return (*env)->NewStringUTF(env, "dlopen failed");
    }

    typedef char* (*func)();
    func f = dlsym(handle, "methodFromSo");
    if (!f) {
        LOGE("dlsym failed: %s", dlerror());
        dlclose(handle);
        (*env)->ReleaseStringUTFChars(env, libpath, libPathC);
        return (*env)->NewStringUTF(env, "methodFromSo not found");
    }

    const char* result = f();  // 实际调用 .so 中的函数
    jstring jResult = (*env)->NewStringUTF(env, result);

    dlclose(handle);
    (*env)->ReleaseStringUTFChars(env, libpath, libPathC);

    return jResult;
}

JNIEXPORT jstring JNICALL
Java_com_xsh_daw_MainActivity_getStringVar(JNIEnv *env, jobject thiz,jstring libpath)
{
    const char *libPathC = (*env)->GetStringUTFChars(env,libpath, NULL);
    void *handle = dlopen(libPathC,RTLD_LAZY);
    char **ptr = dlsym(handle,"a");
    const char* ptra = *ptr;
    dlclose(handle);
    (*env)->ReleaseStringUTFChars(env,libpath,libPathC);
    return (*env)->NewStringUTF(env,ptra);
}

JNIEXPORT jstring JNICALL
Java_com_xsh_daw_MainActivity_hello(JNIEnv *env, jobject thiz)
{
    return (*env)->NewStringUTF(env,"hello");
}

JNIEXPORT void JNICALL
Java_com_xsh_daw_MainActivity_test(JNIEnv *env, jobject thiz,jstring libpath) {
    const char *libPathC = (*env)->GetStringUTFChars(env, libpath, NULL);
    if (!libPathC) {
        LOGE("GetStringUTFChars failed");
    }

    // 1. 打开 .so
    void *handle = dlopen(libPathC, RTLD_LAZY);
    if (!handle) {
        LOGE("dlopen failed: %s", dlerror());

    }

    char **ptr = dlsym(handle, "a");
    if (!ptr) {
        LOGE("dlsym failed: %s", dlerror());
        dlclose(handle);
    }
    typedef char* (*func)();
    func f = dlsym(handle,"methodFromSo");
    if(!f)
    {
        LOGE("dlsym failed: %s", dlerror());
    }
    
    // 3. 使用符号
    const char *ptra = *ptr;
    const char *result = f();
   
    __android_log_print(ANDROID_LOG_DEBUG, "JNI var in so", "%s", ptra);
    __android_log_print(ANDROID_LOG_DEBUG,"JNI func returned var","%s",result);
     // 4. 清理
    dlclose(handle);

    (*env)->ReleaseStringUTFChars(env, libpath, libPathC);

}

// 测试
void init(const char *filename)
{
    void *handle = dlopen(filename,RTLD_LAZY);
    if(!handle)
    {
        LOGE("dlopen failed");
    }
    libstringfromso = handle;
}

JNIEXPORT void JNICALL
Java_com_xsh_daw_MainActivity_init(JNIEnv *env, jobject thiz, jstring libpath)
{
    const char *libPathC = (*env)->GetStringUTFChars(env, libpath, NULL);
    if (!libPathC) {
        LOGE("GetStringUTFChars failed");
    }
    init(libPathC);
}

// 用于测试初始化后，能否正常获取值
JNIEXPORT void JNICALL
Java_com_xsh_daw_MainActivity_getVarAfterInit(JNIEnv *env, jobject thiz)
{
    const char **ptr = dlsym(libstringfromso,"a");
    if(!ptr)
    {
        LOGE("**prt not found");
    }
    const char *resultVar = *ptr;
    LOGD("AfterInit","%s",resultVar);
}

JNIEXPORT void JNICALL
Java_com_xsh_daw_MainActivity_getVar2AfterInit(JNIEnv *env, jobject thiz)
{
    typedef char* (*func)();
    func f = dlsym(libstringfromso,"methodFromSo");
    if(!f){LOGE("function methodFromSo not found");}
    const char *result = f();
    LOGD("AfterInit","%s",result);
    // TODO: implement getVar2AfterInit()
}